﻿using System;
using System.Collections.Generic;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.IO;
using WPFExcelReport;
using WPFExcelReport.Helpers;
using System.Data;
using ReflectionStudio.Core.Events;
namespace WPFExcelReport
{

    /// <summary>
    /// 与客户端的 连接通信类(包含了一个 与客户端 通信的 套接字，和线程)
    /// </summary>
    public class PLCT
    {
        public DataTable TBZLAM
        {
            get;
            set;
        }
        public string DEVTYP
        {
            get;
            set;
        }
        public delegate void DGShowMsg(string strMsg);
        Socket sokMsg;
        DGShowMsg dgShowMsg;//负责 向主窗体文本框显示消息的方法委托
        DGShowMsg dgRemoveConnection;// 负责 从主窗体 中移除 当前连接
        Thread threadMsg;
        public string PLCIP
        {
            get;
            set;
        }
        bool IsRun = false;
        bool IsPortReaday = false;
        public Queue<CommandQ> SendQ = new Queue<CommandQ>();
        #region 构造函数
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sokMsg">通信套接字</param>
        /// <param name="dgShowMsg">向主窗体文本框显示消息的方法委托</param>
        public PLCT(Socket sokMsg, DGShowMsg dgShowMsg, DGShowMsg dgRemoveConnection)
        {
            this.sokMsg = sokMsg;
            string endp = sokMsg.RemoteEndPoint.ToString();
            int idx = endp.IndexOf(':');
            PLCIP = endp.Substring(0, idx);

            this.dgShowMsg = dgShowMsg;
            this.dgRemoveConnection = dgRemoveConnection;
            this.threadMsg = new Thread(RecMsg);
            this.threadMsg.IsBackground = true;
            this.threadMsg.Start();
        }
        public PLCT(Socket sokMsg, DGShowMsg dgRemoveConnection)
        {
            this.sokMsg = sokMsg;
            string endp = sokMsg.RemoteEndPoint.ToString();
            int idx = endp.IndexOf(':');
            PLCIP = endp.Substring(0, idx);
            string filter = "LOCALIP='" + PLCIP + "'";

            this.dgRemoveConnection = dgRemoveConnection;
            this.threadMsg = new Thread(RecMsg);
            this.threadMsg.IsBackground = true;
            this.threadMsg.Start();
        }
        public bool GetDevTyp()
        {
            bool IsLogged = false;
            string filter = "LOCALIP='" + PLCIP + "'";
            DataRow[] rows = TBZLAM.Select(filter);
            if (rows.Length > 0)
            {
                IsLogged = true;
                DEVTYP = rows[0]["DEVTYP"].ToString().Trim();
            }
            else
            {
                DEVTYP = "TBA";
            }
            return IsLogged;
        }
        #endregion

        bool isRec = true;
        #region 02负责监听客户端发送来的消息
        void RecMsg()
        {
            while (isRec)
            {
                try
                {
                    byte[] received = new byte[1024];
                    //接收 对应 客户端发来的消息
                    int length = sokMsg.Receive(received);
                    byte[] data = new byte[length];
                    for (int i = 0; i < length; i++)
                    {
                        data[i] = received[i];
                    }
                    //将接收到的消息数组里真实消息转成字符串
                    string strMsg = System.Text.Encoding.ASCII.GetString(data, 0, length);
                    strMsg = "";
                    foreach (byte b in data)
                    {
                        strMsg += b.ToString() + " ";
                    }
                    Tracer.Info("ZLServer", strMsg);
                    //通过委托 显示消息到 窗体的文本框
                    if (dgShowMsg != null)
                    {
                        dgShowMsg(BitConverter.ToString(data));
                    }

                    switch (DEVTYP.Trim())
                    {
                        case "FXPLC":
                            GetFXMsg(data, length);
                            break;
                        case "S7200":
                            GetS7Msg(data, length);
                            break;
                    }
                }
                catch (Exception ex)
                {
                    isRec = false;
                    //从主窗体中 移除 下拉框中对应的客户端选择项，同时 移除 集合中对应的 PLCT对象
                    dgRemoveConnection(sokMsg.RemoteEndPoint.ToString());
                }


            }
        }
        public void GetFXMsg(byte[] data, int length)
        {

        }
        public void GetS7Msg(byte[] data, int length)
        {
            
            //将接收到的消息数组里真实消息转成字符串  
            if (length > 0)
            {

                //如果接收到的数据长度为1，值为E5H (229)，则为确认码，返回读写确认命令
                if (data[0] == (byte)229 && length == 1)
                { 
                    //收到数据
                    byte[] dataSend = new byte[6];
                    dataSend[0] = 16;
                    //站号
                    dataSend[1] = 0x02;
                    dataSend[2] = 0x00;
                    dataSend[3] = 0x5C;
                    dataSend[4] = (byte)(dataSend[3] + dataSend[1]);
                    dataSend[5] = 0x16;
                    Thread.Sleep(100);
                    sokMsg.Send(dataSend);
                    Thread.Sleep(100);
                }
                else
                {
                    if(data[0] == (byte)229)
                    {
                        IsPortReaday = false;
                    }
                    else
                    {
                        IsPortReaday = true;
                    }
                   
                }
            } 
        }
        #endregion

        #region 03向客户端发送消息
        /// <summary>
        /// 向客户端发送消息
        /// </summary>
        /// <param name="strMsg"></param>
        public void Send(string command, object adres, object count, object DataSend)
        {
            Tracer.Info("ZLServer:发送数据", "address:" + adres.ToString() + ",count:" + count.ToString() + ",DataSend:", DataSend.ToString());
            byte[] bytes = null;
            string[] sWriteData = null;
            switch (DEVTYP.Trim())
            {
                case "FXPLC":
                    switch (command)
                    {
                        case "0":
                            bytes = (byte[])PLCFX.PlcRead(int.Parse((string)adres), int.Parse((string)count), DataSend);
                            break;
                        case "1":
                            sWriteData = ((string)DataSend).Split(',');
                            bytes = (byte[])PLCFX.PlcWrite(int.Parse((string)adres), int.Parse((string)count), sWriteData);
                            break;
                    }
                    break;
                case "S7200":
                    bytes = (byte[])PLCS7.PlcWrite(command, adres, count, DataSend);
                    break;
            }
            if (bytes == null)
                return;
            sokMsg.Send(bytes);
        }
       
        public void AutoRun()
        {
            try
            {
                ThreadStart Work = null;
                Thread Thread = null;
                if (IsRun)
                    return;
                Work = new ThreadStart(DoSendWork);
                Thread = new Thread(Work);
                Thread.Start();

            }
            catch (Exception ex)
            {
                EventDispatcher.Instance.RaiseStatus("发送异常终止", StatusEventType.StopProgress);
                Tracer.Error(ex.StackTrace, ex);
            } 
        }
       
        void DoSendWork()
        {
            if (IsRun)
            {
                return;
            }
            ///若是首个任务，则启动运行，初始化端口为空闲
            IsRun = true;
            IsPortReaday = true;
            while (true)
            {
                while (!IsPortReaday)
                {
                    Thread.Sleep(100);
                }
                if (SendQ.Count == 0
                    && IsPortReaday)
                {
                    IsRun = false;
                    break;
                } 
                CommandQ cq = SendQ.Dequeue();                
                Send(cq.command, cq.adres, cq.count, cq.DataSend);
                IsPortReaday = false;
            }
        }
        #endregion

        #region 06关闭与客户端连接
        /// <summary>
        /// 关闭与客户端连接
        /// </summary>
        public void CloseConnection()
        {
            isRec = false;
        }
        #endregion
    }
}
